home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-M68K / PGTABLE.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  23KB  |  819 lines

  1. #ifndef _M68K_PGTABLE_H
  2. #define _M68K_PGTABLE_H
  3.  
  4. #include <linux/config.h>
  5. #include <asm/setup.h>
  6.  
  7. #ifndef __ASSEMBLY__
  8. #include <asm/processor.h>
  9. #include <linux/tasks.h>
  10.  
  11. /*
  12.  * This file contains the functions and defines necessary to modify and use
  13.  * the m68k page table tree.
  14.  */
  15.  
  16. #include <asm/virtconvert.h>
  17.  
  18. /*
  19.  * Cache handling functions
  20.  */
  21.  
  22. #define flush_icache()                    \
  23. do {                            \
  24.     if (CPU_IS_040_OR_060)                \
  25.         asm __volatile__ ("nop\n\t"        \
  26.                   ".chip 68040\n\t"    \
  27.                   "cinva %%ic\n\t"    \
  28.                   ".chip 68k" : );    \
  29.     else {                        \
  30.         unsigned long _tmp;            \
  31.         asm __volatile__ ("movec %%cacr,%0\n\t"    \
  32.              "orw %1,%0\n\t"            \
  33.              "movec %0,%%cacr"            \
  34.              : "=&d" (_tmp)            \
  35.              : "id" (FLUSH_I));            \
  36.     }                        \
  37. } while (0)
  38.  
  39. /*
  40.  * invalidate the cache for the specified memory range.
  41.  * It starts at the physical address specified for
  42.  * the given number of bytes.
  43.  */
  44. extern void cache_clear (unsigned long paddr, int len);
  45. /*
  46.  * push any dirty cache in the specified memory range.
  47.  * It starts at the physical address specified for
  48.  * the given number of bytes.
  49.  */
  50. extern void cache_push (unsigned long paddr, int len);
  51.  
  52. /*
  53.  * push and invalidate pages in the specified user virtual
  54.  * memory range.
  55.  */
  56. extern void cache_push_v (unsigned long vaddr, int len);
  57.  
  58. /* cache code */
  59. #define FLUSH_I_AND_D    (0x00000808)
  60. #define FLUSH_I     (0x00000008)
  61.  
  62. /* This is needed whenever the virtual mapping of the current
  63.    process changes.  */
  64. #define __flush_cache_all()                        \
  65.     do {                                \
  66.     if (CPU_IS_040_OR_060)                        \
  67.         __asm__ __volatile__ ("nop\n\t"                \
  68.                       ".chip 68040\n\t"            \
  69.                       "cpusha %dc\n\t"            \
  70.                       ".chip 68k");            \
  71.     else {                                \
  72.         unsigned long _tmp;                    \
  73.         __asm__ __volatile__ ("movec %%cacr,%0\n\t"        \
  74.                       "orw %1,%0\n\t"            \
  75.                       "movec %0,%%cacr"            \
  76.                       : "=&d" (_tmp)            \
  77.                       : "di" (FLUSH_I_AND_D));        \
  78.     }                                \
  79.     } while (0)
  80.  
  81. #define __flush_cache_030()                        \
  82.     do {                                \
  83.     if (CPU_IS_020_OR_030) {                    \
  84.         unsigned long _tmp;                    \
  85.         __asm__ __volatile__ ("movec %%cacr,%0\n\t"        \
  86.                       "orw %1,%0\n\t"            \
  87.                       "movec %0,%%cacr"            \
  88.                       : "=&d" (_tmp)            \
  89.                       : "di" (FLUSH_I_AND_D));        \
  90.     }                                \
  91.     } while (0)
  92.  
  93. #define flush_cache_all() __flush_cache_all()
  94.  
  95. extern inline void flush_cache_mm(struct mm_struct *mm)
  96. {
  97.     if (mm == current->mm)
  98.         __flush_cache_030();
  99. }
  100.  
  101. extern inline void flush_cache_range(struct mm_struct *mm,
  102.                      unsigned long start,
  103.                      unsigned long end)
  104. {
  105.     if (mm == current->mm)
  106.             __flush_cache_030();
  107. }
  108.  
  109. extern inline void flush_cache_page(struct vm_area_struct *vma,
  110.                     unsigned long vmaddr)
  111. {
  112.     if (vma->vm_mm == current->mm)
  113.             __flush_cache_030();
  114. }
  115.  
  116. /* Push the page at kernel virtual address and clear the icache */
  117. extern inline void flush_page_to_ram (unsigned long address)
  118. {
  119.     if (CPU_IS_040_OR_060) {
  120.     __asm__ __volatile__ ("nop\n\t"
  121.                   ".chip 68040\n\t"
  122.                   "cpushp %%dc,(%0)\n\t"
  123.                   "cinvp %%ic,(%0)\n\t"
  124.                   ".chip 68k"
  125.                   : : "a" (virt_to_phys((void *)address)));
  126.     }
  127.     else {
  128.     unsigned long _tmp;
  129.     __asm volatile ("movec %%cacr,%0\n\t"
  130.             "orw %1,%0\n\t"
  131.             "movec %0,%%cacr"
  132.             : "=&d" (_tmp)
  133.             : "di" (FLUSH_I));
  134.     }
  135. }
  136.  
  137. /* Push n pages at kernel virtual address and clear the icache */
  138. extern inline void flush_icache_range (unsigned long address,
  139.                        unsigned long endaddr)
  140. {
  141.     if (CPU_IS_040_OR_060) {
  142.     short n = (endaddr - address + PAGE_SIZE - 1) / PAGE_SIZE;
  143.  
  144.     while (n--) {
  145.         __asm__ __volatile__ ("nop\n\t"
  146.                   ".chip 68040\n\t"
  147.                   "cpushp %%dc,(%0)\n\t"
  148.                   "cinvp %%ic,(%0)\n\t"
  149.                   ".chip 68k"
  150.                   : : "a" (virt_to_phys((void *)address)));
  151.         address += PAGE_SIZE;
  152.     }
  153.     }
  154.     else {
  155.     unsigned long _tmp;
  156.     __asm volatile ("movec %%cacr,%0\n\t"
  157.             "orw %1,%0\n\t"
  158.             "movec %0,%%cacr"
  159.             : "=&d" (_tmp)
  160.             : "di" (FLUSH_I));
  161.     }
  162. }
  163.  
  164.  
  165. /*
  166.  * flush all user-space atc entries.
  167.  */
  168. static inline void __flush_tlb(void)
  169. {
  170.     if (CPU_IS_040_OR_060)
  171.         __asm__ __volatile__(".chip 68040\n\t"
  172.                      "pflushan\n\t"
  173.                      ".chip 68k");
  174.     else
  175.         __asm__ __volatile__("pflush #0,#4");
  176. }
  177.  
  178. static inline void __flush_tlb_one(unsigned long addr)
  179. {
  180.     if (CPU_IS_040_OR_060) {
  181.         __asm__ __volatile__(".chip 68040\n\t"
  182.                      "pflush (%0)\n\t"
  183.                      ".chip 68k"
  184.                      : : "a" (addr));
  185.     } else
  186.         __asm__ __volatile__("pflush #0,#4,(%0)" : : "a" (addr));
  187. }
  188.  
  189. #define flush_tlb() __flush_tlb()
  190.  
  191. /*
  192.  * flush all atc entries (both kernel and user-space entries).
  193.  */
  194. static inline void flush_tlb_all(void)
  195. {
  196.     if (CPU_IS_040_OR_060)
  197.         __asm__ __volatile__(".chip 68040\n\t"
  198.                      "pflusha\n\t"
  199.                      ".chip 68k");
  200.     else
  201.         __asm__ __volatile__("pflusha");
  202. }
  203.  
  204. static inline void flush_tlb_mm(struct mm_struct *mm)
  205. {
  206.     if (mm == current->mm)
  207.         __flush_tlb();
  208. }
  209.  
  210. static inline void flush_tlb_page(struct vm_area_struct *vma,
  211.     unsigned long addr)
  212. {
  213.     if (vma->vm_mm == current->mm)
  214.         __flush_tlb_one(addr);
  215. }
  216.  
  217. static inline void flush_tlb_range(struct mm_struct *mm,
  218.     unsigned long start, unsigned long end)
  219. {
  220.     if (mm == current->mm)
  221.         __flush_tlb();
  222. }
  223.  
  224. extern inline void flush_tlb_kernel_page(unsigned long addr)
  225. {
  226.     if (CPU_IS_040_OR_060) {
  227.         mm_segment_t old_fs = get_fs();
  228.         set_fs(KERNEL_DS);
  229.         __asm__ __volatile__(".chip 68040\n\t"
  230.                      "pflush (%0)\n\t"
  231.                      ".chip 68k"
  232.                      : : "a" (addr));
  233.         set_fs(old_fs);
  234.     } else
  235.         __asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr));
  236. }
  237.  
  238. /* Certain architectures need to do special things when pte's
  239.  * within a page table are directly modified.  Thus, the following
  240.  * hook is made available.
  241.  */
  242. #define set_pte(pteptr, pteval)                    \
  243.     do{                            \
  244.         *(pteptr) = (pteval);                \
  245.     } while(0)
  246.  
  247.  
  248. /* PMD_SHIFT determines the size of the area a second-level page table can map */
  249. #define PMD_SHIFT    22
  250. #define PMD_SIZE    (1UL << PMD_SHIFT)
  251. #define PMD_MASK    (~(PMD_SIZE-1))
  252.  
  253. /* PGDIR_SHIFT determines what a third-level page table entry can map */
  254. #define PGDIR_SHIFT    25
  255. #define PGDIR_SIZE    (1UL << PGDIR_SHIFT)
  256. #define PGDIR_MASK    (~(PGDIR_SIZE-1))
  257.  
  258. /*
  259.  * entries per page directory level: the m68k is configured as three-level,
  260.  * so we do have PMD level physically.
  261.  */
  262. #define PTRS_PER_PTE    1024
  263. #define PTRS_PER_PMD    8
  264. #define PTRS_PER_PGD    128
  265. #define USER_PTRS_PER_PGD    (TASK_SIZE/PGDIR_SIZE)
  266.  
  267. /* the no. of pointers that fit on a page: this will go away */
  268. #define PTRS_PER_PAGE    (PAGE_SIZE/sizeof(void*))
  269.  
  270. typedef pgd_t pgd_table[PTRS_PER_PGD];
  271. typedef pmd_t pmd_table[PTRS_PER_PMD];
  272. typedef pte_t pte_table[PTRS_PER_PTE];
  273.  
  274. #define PGD_TABLES_PER_PAGE (PAGE_SIZE/sizeof(pgd_table))
  275. #define PMD_TABLES_PER_PAGE (PAGE_SIZE/sizeof(pmd_table))
  276. #define PTE_TABLES_PER_PAGE (PAGE_SIZE/sizeof(pte_table))
  277.  
  278. typedef pgd_table pgd_tablepage[PGD_TABLES_PER_PAGE];
  279. typedef pmd_table pmd_tablepage[PMD_TABLES_PER_PAGE];
  280. typedef pte_table pte_tablepage[PTE_TABLES_PER_PAGE];
  281.  
  282. /* Virtual address region for use by kernel_map() */
  283. #define    KMAP_START    0xd0000000
  284. #define    KMAP_END    0xf0000000
  285.  
  286. /* Just any arbitrary offset to the start of the vmalloc VM area: the
  287.  * current 8MB value just means that there will be a 8MB "hole" after the
  288.  * physical memory until the kernel virtual memory starts.  That means that
  289.  * any out-of-bounds memory accesses will hopefully be caught.
  290.  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
  291.  * area for the same reason. ;)
  292.  */
  293. #define VMALLOC_OFFSET    (8*1024*1024)
  294. #define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
  295. #define VMALLOC_VMADDR(x) ((unsigned long)(x))
  296. #define VMALLOC_END KMAP_START
  297.  
  298. #endif /* __ASSEMBLY__ */
  299.  
  300. /*
  301.  * Definitions for MMU descriptors
  302.  */
  303. #define _PAGE_PRESENT    0x001
  304. #define _PAGE_SHORT    0x002
  305. #define _PAGE_RONLY    0x004
  306. #define _PAGE_ACCESSED    0x008
  307. #define _PAGE_DIRTY    0x010
  308. #define _PAGE_SUPER    0x080    /* 68040 supervisor only */
  309. #define _PAGE_FAKE_SUPER 0x200    /* fake supervisor only on 680[23]0 */
  310. #define _PAGE_GLOBAL040    0x400    /* 68040 global bit, used for kva descs */
  311. #define _PAGE_COW    0x800    /* implemented in software */
  312. #define _PAGE_NOCACHE030 0x040    /* 68030 no-cache mode */
  313. #define _PAGE_NOCACHE    0x060    /* 68040 cache mode, non-serialized */
  314. #define _PAGE_NOCACHE_S    0x040    /* 68040 no-cache mode, serialized */
  315. #define _PAGE_CACHE040    0x020    /* 68040 cache mode, cachable, copyback */
  316. #define _PAGE_CACHE040W    0x000    /* 68040 cache mode, cachable, write-through */
  317.  
  318. #define _DESCTYPE_MASK    0x003
  319.  
  320. #define _CACHEMASK040    (~0x060)
  321. #define _TABLE_MASK    (0xfffffe00)
  322.  
  323. #define _PAGE_TABLE    (_PAGE_SHORT)
  324. #define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_NOCACHE)
  325.  
  326. #ifndef __ASSEMBLY__
  327.  
  328. /* This is the cache mode to be used for pages containing page descriptors for
  329.  * processors >= '040. It is in pte_mknocache(), and the variable is defined
  330.  * and initialized in head.S */
  331. extern int m68k_pgtable_cachemode;
  332.  
  333. /* This is the cache mode for normal pages, for supervisor access on
  334.  * processors >= '040. It is used in pte_mkcache(), and the variable is
  335.  * defined and initialized in head.S */
  336.  
  337. #if defined(CONFIG_060_WRITETHROUGH)
  338. extern int m68k_supervisor_cachemode;
  339. #else
  340. #define m68k_supervisor_cachemode _PAGE_CACHE040
  341. #endif
  342.  
  343. #if defined(CPU_M68040_OR_M68060_ONLY)
  344. #define mm_cachebits _PAGE_CACHE040
  345. #elif defined(CPU_M68020_OR_M68030_ONLY)
  346. #define mm_cachebits 0
  347. #else
  348. extern unsigned long mm_cachebits;
  349. #endif
  350.  
  351. #define PAGE_NONE    __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | mm_cachebits)
  352. #define PAGE_SHARED    __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | mm_cachebits)
  353. #define PAGE_COPY    __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | mm_cachebits)
  354. #define PAGE_READONLY    __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | mm_cachebits)
  355. #define PAGE_KERNEL    __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED | mm_cachebits)
  356.  
  357. /* Alternate definitions that are compile time constants, for
  358.    initializing protection_map.  The cachebits are fixed later.  */
  359. #define PAGE_NONE_C    __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED)
  360. #define PAGE_SHARED_C    __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
  361. #define PAGE_COPY_C    __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED)
  362. #define PAGE_READONLY_C    __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED)
  363.  
  364. /*
  365.  * The m68k can't do page protection for execute, and considers that the same are read.
  366.  * Also, write permissions imply read permissions. This is the closest we can get..
  367.  */
  368. #define __P000    PAGE_NONE_C
  369. #define __P001    PAGE_READONLY_C
  370. #define __P010    PAGE_COPY_C
  371. #define __P011    PAGE_COPY_C
  372. #define __P100    PAGE_READONLY_C
  373. #define __P101    PAGE_READONLY_C
  374. #define __P110    PAGE_COPY_C
  375. #define __P111    PAGE_COPY_C
  376.  
  377. #define __S000    PAGE_NONE_C
  378. #define __S001    PAGE_READONLY_C
  379. #define __S010    PAGE_SHARED_C
  380. #define __S011    PAGE_SHARED_C
  381. #define __S100    PAGE_READONLY_C
  382. #define __S101    PAGE_READONLY_C
  383. #define __S110    PAGE_SHARED_C
  384. #define __S111    PAGE_SHARED_C
  385.  
  386. /* zero page used for uninitialized stuff */
  387. extern unsigned long empty_zero_page;
  388.  
  389. /*
  390.  * BAD_PAGETABLE is used when we need a bogus page-table, while
  391.  * BAD_PAGE is used for a bogus page.
  392.  *
  393.  * ZERO_PAGE is a global shared page that is always zero: used
  394.  * for zero-mapped memory areas etc..
  395.  */
  396. extern pte_t __bad_page(void);
  397. extern pte_t * __bad_pagetable(void);
  398.  
  399. #define BAD_PAGETABLE __bad_pagetable()
  400. #define BAD_PAGE __bad_page()
  401. #define ZERO_PAGE empty_zero_page
  402.  
  403. /* number of bits that fit into a memory pointer */
  404. #define BITS_PER_PTR            (8*sizeof(unsigned long))
  405.  
  406. /* to align the pointer to a pointer address */
  407. #define PTR_MASK            (~(sizeof(void*)-1))
  408.  
  409. /* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
  410. /* 64-bit machines, beware!  SRB. */
  411. #define SIZEOF_PTR_LOG2            2
  412.  
  413. /* to find an entry in a page-table */
  414. #define PAGE_PTR(address) \
  415. ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
  416.  
  417. /*
  418.  * Conversion functions: convert a page and protection to a page entry,
  419.  * and a page entry and page directory to the page they refer to.
  420.  */
  421. #define mk_pte(page, pgprot) \
  422. ({ pte_t __pte; pte_val(__pte) = virt_to_phys((void *)page) + pgprot_val(pgprot); __pte; })
  423. #define mk_pte_phys(physpage, pgprot) \
  424. ({ pte_t __pte; pte_val(__pte) = (unsigned long)physpage + pgprot_val(pgprot); __pte; })
  425.  
  426. extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
  427. { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
  428.  
  429. extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
  430. {
  431.     int i;
  432.     unsigned long ptbl;
  433.     ptbl = virt_to_phys(ptep);
  434.     for (i = 0; i < 16; i++, ptbl += sizeof(pte_table)/16)
  435.         pmdp->pmd[i] = _PAGE_TABLE | _PAGE_ACCESSED | ptbl;
  436. }
  437.  
  438. extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
  439. { pgd_val(*pgdp) = _PAGE_TABLE | _PAGE_ACCESSED | virt_to_phys(pmdp); }
  440.  
  441. extern inline unsigned long pte_page(pte_t pte)
  442. { return (unsigned long)phys_to_virt(pte_val(pte) & PAGE_MASK); }
  443.  
  444. extern inline unsigned long pmd_page2(pmd_t *pmd)
  445. { return (unsigned long)phys_to_virt(pmd_val(*pmd) & _TABLE_MASK); }
  446. #define pmd_page(pmd) pmd_page2(&(pmd))
  447.  
  448. extern inline unsigned long pgd_page(pgd_t pgd)
  449. { return (unsigned long)phys_to_virt(pgd_val(pgd) & _TABLE_MASK); }
  450.  
  451. extern inline int pte_none(pte_t pte)        { return !pte_val(pte); }
  452. extern inline int pte_present(pte_t pte)    { return pte_val(pte) & (_PAGE_PRESENT | _PAGE_FAKE_SUPER); }
  453. extern inline void pte_clear(pte_t *ptep)    { pte_val(*ptep) = 0; }
  454.  
  455. extern inline int pmd_none2(pmd_t *pmd)        { return !pmd_val(*pmd); }
  456. #define pmd_none(pmd) pmd_none2(&(pmd))
  457. extern inline int pmd_bad2(pmd_t *pmd)        { return (pmd_val(*pmd) & _DESCTYPE_MASK) != _PAGE_TABLE; }
  458. #define pmd_bad(pmd) pmd_bad2(&(pmd))
  459. extern inline int pmd_present2(pmd_t *pmd)    { return pmd_val(*pmd) & _PAGE_TABLE; }
  460. #define pmd_present(pmd) pmd_present2(&(pmd))
  461. extern inline void pmd_clear(pmd_t * pmdp)
  462. {
  463.     short i;
  464.  
  465.     for (i = 15; i >= 0; i--)
  466.         pmdp->pmd[i] = 0;
  467. }
  468.  
  469. extern inline int pgd_none(pgd_t pgd)        { return !pgd_val(pgd); }
  470. extern inline int pgd_bad(pgd_t pgd)        { return (pgd_val(pgd) & _DESCTYPE_MASK) != _PAGE_TABLE; }
  471. extern inline int pgd_present(pgd_t pgd)    { return pgd_val(pgd) & _PAGE_TABLE; }
  472.  
  473. extern inline void pgd_clear(pgd_t * pgdp)    { pgd_val(*pgdp) = 0; }
  474.  
  475. /*
  476.  * The following only work if pte_present() is true.
  477.  * Undefined behaviour if not..
  478.  */
  479. extern inline int pte_read(pte_t pte)        { return 1; }
  480. extern inline int pte_write(pte_t pte)        { return !(pte_val(pte) & _PAGE_RONLY); }
  481. extern inline int pte_exec(pte_t pte)        { return 1; }
  482. extern inline int pte_dirty(pte_t pte)        { return pte_val(pte) & _PAGE_DIRTY; }
  483. extern inline int pte_young(pte_t pte)        { return pte_val(pte) & _PAGE_ACCESSED; }
  484.  
  485. extern inline pte_t pte_wrprotect(pte_t pte)    { pte_val(pte) |= _PAGE_RONLY; return pte; }
  486. extern inline pte_t pte_rdprotect(pte_t pte)    { return pte; }
  487. extern inline pte_t pte_exprotect(pte_t pte)    { return pte; }
  488. extern inline pte_t pte_mkclean(pte_t pte)    { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
  489. extern inline pte_t pte_mkold(pte_t pte)    { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
  490. extern inline pte_t pte_mkwrite(pte_t pte)    { pte_val(pte) &= ~_PAGE_RONLY; return pte; }
  491. extern inline pte_t pte_mkread(pte_t pte)    { return pte; }
  492. extern inline pte_t pte_mkexec(pte_t pte)    { return pte; }
  493. extern inline pte_t pte_mkdirty(pte_t pte)    { pte_val(pte) |= _PAGE_DIRTY; return pte; }
  494. extern inline pte_t pte_mkyoung(pte_t pte)    { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
  495. extern inline pte_t pte_mknocache(pte_t pte)
  496. {
  497.     pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_pgtable_cachemode;
  498.     return pte;
  499. }
  500. extern inline pte_t pte_mkcache(pte_t pte)    { pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_supervisor_cachemode; return pte; }
  501.  
  502. /* to set the page-dir */
  503. extern inline void SET_PAGE_DIR(struct task_struct * tsk, pgd_t * pgdir)
  504. {
  505.     tsk->tss.crp[0] = 0x80000000 | _PAGE_TABLE;
  506.     tsk->tss.crp[1] = virt_to_phys(pgdir);
  507.     if (tsk == current) {
  508.         if (CPU_IS_040_OR_060)
  509.             __asm__ __volatile__ (".chip 68040\n\t"
  510.                           "movec %0,%%urp\n\t"
  511.                           ".chip 68k"
  512.                           : : "r" (tsk->tss.crp[1]));
  513.         else {
  514.             unsigned long tmp;
  515.             __asm__ __volatile__ ("movec  %%cacr,%0\n\t"
  516.                           "orw #0x0808,%0\n\t"
  517.                           "movec %0,%%cacr\n\t"
  518.                           "pmove %1,%%crp\n\t"
  519.                           : "=d" (tmp)
  520.                           : "m" (tsk->tss.crp[0]));
  521.         }
  522.     }
  523. }
  524.  
  525. #define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address))
  526.  
  527. /* to find an entry in a page-table-directory */
  528. extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
  529. {
  530.     return mm->pgd + (address >> PGDIR_SHIFT);
  531. }
  532.  
  533. #define swapper_pg_dir kernel_pg_dir
  534. extern pgd_t kernel_pg_dir[128];
  535.  
  536. extern inline pgd_t * pgd_offset_k(unsigned long address)
  537. {
  538.     return kernel_pg_dir + (address >> PGDIR_SHIFT);
  539. }
  540.  
  541.  
  542. /* Find an entry in the second-level page table.. */
  543. extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
  544. {
  545.     return (pmd_t *) pgd_page(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PMD-1));
  546. }
  547.  
  548. /* Find an entry in the third-level page table.. */ 
  549. extern inline pte_t * pte_offset(pmd_t * pmdp, unsigned long address)
  550. {
  551.     return (pte_t *) pmd_page(*pmdp) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
  552. }
  553.  
  554. /*
  555.  * Allocate and free page tables. The xxx_kernel() versions are
  556.  * used to allocate a kernel page table - this turns on ASN bits
  557.  * if any.
  558.  */
  559.  
  560. /* Prior to calling these routines, the page should have been flushed
  561.  * from both the cache and ATC, or the CPU might not notice that the
  562.  * cache setting for the page has been changed. -jskov
  563.  */
  564. static inline void nocache_page (unsigned long vaddr)
  565. {
  566.     if (CPU_IS_040_OR_060) {
  567.         pgd_t *dir;
  568.         pmd_t *pmdp;
  569.         pte_t *ptep;
  570.  
  571.         dir = pgd_offset_k(vaddr);
  572.         pmdp = pmd_offset(dir,vaddr);
  573.         ptep = pte_offset(pmdp,vaddr);
  574.         *ptep = pte_mknocache(*ptep);
  575.     }
  576. }
  577.  
  578. static inline void cache_page (unsigned long vaddr)
  579. {
  580.     if (CPU_IS_040_OR_060) {
  581.         pgd_t *dir;
  582.         pmd_t *pmdp;
  583.         pte_t *ptep;
  584.  
  585.         dir = pgd_offset_k(vaddr);
  586.         pmdp = pmd_offset(dir,vaddr);
  587.         ptep = pte_offset(pmdp,vaddr);
  588.         *ptep = pte_mkcache(*ptep);
  589.     }
  590. }
  591.  
  592. extern struct pgtable_cache_struct {
  593.     unsigned long *pmd_cache;
  594.     unsigned long *pte_cache;
  595. /* This counts in units of pointer tables, of which can be eight per page. */
  596.     unsigned long pgtable_cache_sz;
  597. } quicklists;
  598.  
  599. #define pgd_quicklist ((unsigned long *)0)
  600. #define pmd_quicklist (quicklists.pmd_cache)
  601. #define pte_quicklist (quicklists.pte_cache)
  602. /* This isn't accurate because of fragmentation of allocated pages for
  603.    pointer tables, but that should not be a problem. */
  604. #define pgtable_cache_size ((quicklists.pgtable_cache_sz+7)/8)
  605.  
  606. extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset);
  607. extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset);
  608.  
  609. extern pmd_t *get_pointer_table(void);
  610. extern int free_pointer_table(pmd_t *);
  611.  
  612. extern __inline__ pte_t *get_pte_fast(void)
  613. {
  614.     unsigned long *ret;
  615.  
  616.     ret = pte_quicklist;
  617.     if (ret) {
  618.         pte_quicklist = (unsigned long *)*ret;
  619.         ret[0] = 0;
  620.         quicklists.pgtable_cache_sz -= 8;
  621.     }
  622.     return (pte_t *)ret;
  623. }
  624.  
  625. extern __inline__ void free_pte_fast(pte_t *pte)
  626. {
  627.     *(unsigned long *)pte = (unsigned long)pte_quicklist;
  628.     pte_quicklist = (unsigned long *)pte;
  629.     quicklists.pgtable_cache_sz += 8;
  630. }
  631.  
  632. extern __inline__ void free_pte_slow(pte_t *pte)
  633. {
  634.     cache_page((unsigned long)pte);
  635.     free_page((unsigned long) pte);
  636. }
  637.  
  638. extern __inline__ pmd_t *get_pmd_fast(void)
  639. {
  640.     unsigned long *ret;
  641.  
  642.     ret = pmd_quicklist;
  643.     if (ret) {
  644.         pmd_quicklist = (unsigned long *)*ret;
  645.         ret[0] = 0;
  646.         quicklists.pgtable_cache_sz--;
  647.     }
  648.     return (pmd_t *)ret;
  649. }
  650.  
  651. extern __inline__ void free_pmd_fast(pmd_t *pmd)
  652. {
  653.     *(unsigned long *)pmd = (unsigned long)pmd_quicklist;
  654.     pmd_quicklist = (unsigned long *) pmd;
  655.     quicklists.pgtable_cache_sz++;
  656. }
  657.  
  658. extern __inline__ int free_pmd_slow(pmd_t *pmd)
  659. {
  660.     return free_pointer_table(pmd);
  661. }
  662.  
  663. /* The pgd cache is folded into the pmd cache, so these are dummy routines. */
  664. extern __inline__ pgd_t *get_pgd_fast(void)
  665. {
  666.     return (pgd_t *)0;
  667. }
  668.  
  669. extern __inline__ void free_pgd_fast(pgd_t *pgd)
  670. {
  671. }
  672.  
  673. extern __inline__ void free_pgd_slow(pgd_t *pgd)
  674. {
  675. }
  676.  
  677. extern void __bad_pte(pmd_t *pmd);
  678. extern void __bad_pmd(pgd_t *pgd);
  679.  
  680. extern inline void pte_free(pte_t * pte)
  681. {
  682.     free_pte_fast(pte);
  683. }
  684.  
  685. extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
  686. {
  687.     address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
  688.     if (pmd_none(*pmd)) {
  689.         pte_t * page = get_pte_fast();
  690.  
  691.         if (!page)
  692.             return get_pte_slow(pmd, address);
  693.         pmd_set(pmd,page);
  694.         return page + address;
  695.     }
  696.     if (pmd_bad(*pmd)) {
  697.         __bad_pte(pmd);
  698.         return NULL;
  699.     }
  700.     return (pte_t *) pmd_page(*pmd) + address;
  701. }
  702.  
  703. extern inline void pmd_free(pmd_t * pmd)
  704. {
  705.     free_pmd_fast(pmd);
  706. }
  707.  
  708. extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
  709. {
  710.     address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
  711.     if (pgd_none(*pgd)) {
  712.         pmd_t *page = get_pmd_fast();
  713.  
  714.         if (!page)
  715.             return get_pmd_slow(pgd, address);
  716.         pgd_set(pgd, page);
  717.         return page + address;
  718.     }
  719.     if (pgd_bad(*pgd)) {
  720.         __bad_pmd(pgd);
  721.         return NULL;
  722.     }
  723.     return (pmd_t *) pgd_page(*pgd) + address;
  724. }
  725.  
  726. extern inline void pte_free_kernel(pte_t * pte)
  727. {
  728.     free_pte_fast(pte);
  729. }
  730.  
  731. extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
  732. {
  733.     return pte_alloc(pmd, address);
  734. }
  735.  
  736. extern inline void pmd_free_kernel(pmd_t * pmd)
  737. {
  738.     free_pmd_fast(pmd);
  739. }
  740.  
  741. extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
  742. {
  743.     return pmd_alloc(pgd, address);
  744. }
  745.  
  746. extern inline void pgd_free(pgd_t * pgd)
  747. {
  748.     free_pmd_fast((pmd_t *)pgd);
  749. }
  750.  
  751. extern inline pgd_t * pgd_alloc(void)
  752. {
  753.     pgd_t *pgd = (pgd_t *)get_pmd_fast();
  754.     if (!pgd)
  755.         pgd = (pgd_t *)get_pointer_table();
  756.     return pgd;
  757. }
  758.  
  759. extern int do_check_pgt_cache(int, int);
  760.  
  761. extern inline void set_pgdir(unsigned long address, pgd_t entry)
  762. {
  763. }
  764.  
  765. /*
  766.  * Check if the addr/len goes up to the end of a physical
  767.  * memory chunk.  Used for DMA functions.
  768.  */
  769. #ifdef CONFIG_SINGLE_MEMORY_CHUNK
  770. /*
  771.  * It makes no sense to consider whether we cross a memory boundary if
  772.  * we support just one physical chunk of memory.
  773.  */
  774. extern inline int mm_end_of_chunk (unsigned long addr, int len)
  775. {
  776.     return 0;
  777. }
  778. #else
  779. int mm_end_of_chunk (unsigned long addr, int len);
  780. #endif
  781.  
  782. extern void kernel_set_cachemode(void *addr, unsigned long size, int cmode);
  783.  
  784. /*
  785.  * The m68k doesn't have any external MMU info: the kernel page
  786.  * tables contain all the necessary information.
  787.  */
  788. extern inline void update_mmu_cache(struct vm_area_struct * vma,
  789.     unsigned long address, pte_t pte)
  790. {
  791. }
  792.  
  793. /*
  794.  * I don't know what is going on here, but since these were changed,
  795.  * swapping hasn't been working on the 68040.
  796.  */
  797. /* With the new handling of PAGE_NONE the old definitions definitely
  798.    don't work any more.  */
  799.  
  800. #define SWP_TYPE(entry)  (((entry) >> 2) & 0x7f)
  801. #if 0
  802. #define SWP_OFFSET(entry) ((entry) >> 9)
  803. #define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 9))
  804. #else
  805. #define SWP_OFFSET(entry) ((entry) >> PAGE_SHIFT)
  806. #define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << PAGE_SHIFT))
  807. #endif
  808.  
  809. #endif /* __ASSEMBLY__ */
  810.  
  811. #define module_map      vmalloc
  812. #define module_unmap    vfree
  813.  
  814. /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
  815. #define PageSkip(page)        (0)
  816. #define kern_addr_valid(addr)    (1)
  817.  
  818. #endif /* _M68K_PGTABLE_H */
  819.